window.drawSummaryChart = {
  ctx: null,
  ratio: null,
  // 绘制圆(Canvas的圆弧是从三点钟方向, 默认是顺时针方向的反方向开始画, 比较不好理解, 所以我改成负值, 让它和绘制方向同向)
  drawCircle: function drawCircle (options) {
    var ctx = this.ctx, ratio = this.ratio,
      offset = options.offset || {x: 0, y: 0},
      x = (offset.x + options.x) * ratio,
      y = (offset.y + options.y) * ratio,
      r = options.r * ratio,
      color = options.color

    ctx.fillStyle = color // 设置填充颜色
    ctx.beginPath() // 开始创建一个路径
    ctx.moveTo(x + r, -y) // 移动到圆弧的起始点(三点钟位置)
    ctx.arc(x, -y, r, 0, -2 * Math.PI, true) // 绘制一个圆
    ctx.closePath() // 关闭一个路径
    ctx.fill() // 填充内部色
  },
  // 绘制线条
  drawLine: function drawLine (options) {
    var ctx = this.ctx, ratio = this.ratio,
      offset = options.offset || {x: 0, y: 0},
      x1 = (offset.x + options.x1) * ratio,
      y1 = (offset.y + options.y1) * ratio,
      x2 = (offset.x + options.x2) * ratio,
      y2 = (offset.y + options.y2) * ratio,
      color = options.color,
      width = options.width * ratio

    ctx.lineWidth = width // 设置线宽
    ctx.strokeStyle = color // 设置边框颜色
    ctx.beginPath() // 开始创建一个路径
    ctx.moveTo(x1, -y1) // 移动线段起点
    ctx.lineTo(x2, -y2) // 绘制直线
    ctx.closePath() // 关闭一个路径
    ctx.stroke() // 填充边框颜色
  },
  // 绘制多边形
  drawPolygon: function drawPolygon (options) {
    var ctx = this.ctx, ratio = this.ratio,
      polygons = options.polygons,
      offset = options.offset || {x: 0, y: 0},
      fillColor = options.fillColor,
      strokeColor = options.strokeColor,
      strokeWidth = options.strokeWidth * ratio

    ctx.fillStyle = fillColor // 设置填充颜色
    ctx.strokeStyle = strokeColor // 设置边框颜色
    ctx.lineWidth = strokeWidth // 设置线宽

    ctx.beginPath() // 开始创建一个路径
    for (var i = 0; i < polygons.length; i++) {
      var polygon = polygons[i]
      var current = {
        x: polygon.x,
        y: polygon.y
      }
      // 转换坐标偏移
      if (offset) {
        current.x = this.offsetCartesianCoor(offset, polygon).x
        current.y = this.offsetCartesianCoor(offset, polygon).y
      }
      current.x = current.x * ratio
      current.y = current.y * ratio
      if (i === 0) ctx.moveTo(current.x, -current.y) // 移动到多边形起点
      else ctx.lineTo(current.x, -current.y) // 绘制直线
    }
    // 终点和起点闭合
    var _offsetCartesianCoor = this.offsetCartesianCoor(offset, polygons[0]),
      x = _offsetCartesianCoor.x * ratio,
      y = _offsetCartesianCoor.y * ratio

    ctx.lineTo(x, -y)
    ctx.closePath() // 关闭一个路径

    ctx.stroke()    // 填充边框颜色
    ctx.fill()      // 填充内部色
  },
  // 绘制文本
  drawText: function (options) {
    var ctx = this.ctx, ratio = this.ratio,
      offset = options.offset || {x: 0, y: 0},
      text = options.text,
      color = options.color,
      font = options.font

    ctx.font = font
    ctx.fillStyle = color
    ctx.fillText(text, offset.x * ratio, offset.y * ratio)
  },
  // 角度转弧度
  angleToRadian: function angleToRadian (angle) {
    return angle * Math.PI / 180
  },
  // 极坐标转笛卡尔坐标
  polarCoorToCartesianCoor: function polarCoorToCartesianCoor (angle, r) {
    return {
      x: angle % 90 == 0 && angle % 180 != 0 ? 0 : r * Math.cos(this.angleToRadian(angle)),
      y: angle % 180 == 0 ? 0 : r * Math.sin(this.angleToRadian(angle))
    }
  },
  // 将线条个数转角度数组(6点钟开始顺时针顺序)
  lineNumToAngles: function lineNumToAngles (num) {
    var arr = []
    for (var i = 0; i < num; i++) {
      arr.push(-90 - i * 360 / num)
    }
    return arr
  },
  // 笛卡尔坐标偏移
  offsetCartesianCoor: function offsetCartesianCoor (offset, coor) {
    return {
      x: offset.x + coor.x,
      y: offset.y + coor.y
    }
  },
  // 分数转多边形坐标
  scoresToCoor: function scoresToCoor (scores) {
    var angles = this.lineNumToAngles(scores.length)
    var polygons = [{
      x: 0,
      y: this.polarCoorToCartesianCoor(angles[0], scores[0]).y
    }]
    for (var i = 0; i < angles.length; i++) {
      polygons.push(this.polarCoorToCartesianCoor(angles[i], scores[i]))
    }
    return polygons
  },
  // 获取象限
  getQuadrant: function getQuadrant (coor) {
    var quadrant = {
      x: coor.x > 0 ? 1 : coor.x < 0 ? -1 : 0,
      y: coor.y > 0 ? 1 : coor.y < 0 ? -1 : 0
    }
    if (quadrant.x === 1 && quadrant.y === 1) return 1
    else if (quadrant.x === 0 && quadrant.y === 1) return 2
    else if (quadrant.x === -1 && quadrant.y === 1) return 3
    else if (quadrant.x === -1 && quadrant.y === 0) return 4
    else if (quadrant.x === -1 && quadrant.y === -1) return 5
    else if (quadrant.x === 0 && quadrant.y === -1) return 6
    else if (quadrant.x === 1 && quadrant.y === -1) return 7
    else if (quadrant.x === 1 && quadrant.y === 0) return 8
    else return -1
  },
  // 计算分数文本坐标(Canvas文本的坐标基准是左下角的点)
  getScoreTextCoor: function getScoreTextCoor (coor, quadrant) {
    var w = 28,
      h = 14,
      o = 10,
      x = coor.x,
      y = coor.y
    switch (quadrant) {
      case 1:
        return {
          x: x + o,
          y: y + o + h
        }
      case 2:
        return {
          x: x - w / 2,
          y: y + o + h + o / 2
        }
      case 3:
        return {
          x: x - w - o,
          y: y + o + h
        }
      case 4:
        return {
          x: x - w - o,
          y: y + o / 2
        }
      case 5:
        return {
          x: x - w - o,
          y: y - h
        }
      case 6:
        return {
          x: x - w / 2,
          y: y - h - o
        }
      case 7:
        return {
          x: x + o,
          y: y - h
        }
      case 8:
        return {
          x: x + o,
          y: y + o / 2
        }
    }
  },
  // 计算题型文本坐标(Canvas文本的坐标基准是左下角的点)
  getSummaryTextCoor: function getSummaryTextCoor (coor, quadrant) {
    var w = 28,
      h = 14,
      o = 10,
      x = coor.x,
      y = coor.y
    switch (quadrant) {
      case 1:
        return {
          x: x + o,
          y: y + o / 2
        }
      case 2:
        return {
          x: x - w / 2,
          y: y + o
        }
      case 3:
        return {
          x: x - w - o,
          y: y + o / 2
        }
      case 4:
        return {
          x: x - w - o,
          y: y - h
        }
      case 5:
        return {
          x: x - w - o,
          y: y - h * 2 - o / 2
        }
      case 6:
        return {
          x: x - w / 2,
          y: y - h * 2 - o - o / 2
        }
      case 7:
        return {
          x: x + o,
          y: y - h * 2 - o / 2
        }
      case 8:
        return {
          x: x + o,
          y: y - h
        }
    }
  },
  // 获取屏幕分辨率
  getRatio: function () {
    var ctx = this.ctx
    var devicePixelRatio = window.devicePixelRatio || 1
    var backingStorePixelRatio = ctx.webkitBackingStorePixelRatio ||
      ctx.mozBackingStorePixelRatio ||
      ctx.msBackingStorePixelRatio ||
      ctx.oBackingStorePixelRatio ||
      ctx.backingStorePixelRatio || 1
    return devicePixelRatio / backingStorePixelRatio
  },
  // 生成测试结果图
  init: function init (options) {
    var _ctx = options.ctx,
      canvas = options.canvas,
      canvasId = options.canvasId,
      width = options.width,
      height = options.height,
      ratio = this.ratio = options.ratio || null,
      summary = options.summary,
      pass = options.pass,
      offset = options.offset

    // 获取绘图上下文 context
    var ctx = null
    if (_ctx) {
      ctx = this.ctx = _ctx
      if (!ratio) ratio = this.ratio = this.getRatio()
    } else if (canvas) {
      ctx = this.ctx = canvas.getContext('2d')
      if (!ratio) ratio = this.ratio = this.getRatio()
      canvas.width = width * ratio
      canvas.height = height * ratio
    } else if (canvasId) {
      canvas = document.getElementById(canvasId)
      ctx = this.ctx = canvas.getContext('2d')
      if (!ratio) ratio = this.ratio = this.getRatio()
      canvas.width = width * ratio
      canvas.height = height * ratio
    }
    else {
      console.log('canvas 参数错误, 应至少传入ctx, canvas, canvasId中的一个')
      return
    }

    var scores = [], scoreText = []
    if (summary.vocabulary) {
      scores.push(summary.vocabulary)
      scoreText.push('词汇')
    }
    if (summary.reading) {
      scores.push(summary.reading)
      scoreText.push('阅读')
    }
    if (summary.pronunciation) {
      scores.push(summary.pronunciation)
      scoreText.push('语音')
    }
    if (summary.listening) {
      scores.push(summary.listening)
      scoreText.push('听力')
    }
    if (summary.grammar) {
      scores.push(summary.grammar)
      scoreText.push('语法')
    }

    // 设置及格分数线
    pass = pass || 0.7

    // 设置偏移量
    offset = offset || {
      x: 175,
      y: -175
    }

    // 定义圆心
    var center = {x: 0, y: 0}, r = 100

    // 绘制100分圆
    this.drawCircle({
      x: center.x,
      y: center.y,
      r: r,
      offset: offset,
      color: 'rgba(126, 240, 255, 0.1)'
    })
    // 绘制70分圆
    this.drawCircle({
      x: center.x,
      y: center.y,
      r: r * pass,
      offset: offset,
      color: 'rgba(156, 241, 255, 0.2)'
    })
    // 绘制40分圆
    this.drawCircle({
      x: center.x,
      y: center.y,
      r: r * 0.4,
      offset: offset,
      color: 'rgba(156, 241, 255, 0.3)'
    })
    // 绘制多边形
    this.drawPolygon({
      polygons: this.scoresToCoor(scores),
      offset: offset,
      fillColor: 'rgba(47, 204, 255, 0.3)',
      strokeColor: 'rgba(50, 205, 255, 1)',
      strokeWidth: 2
    })
    // 线长和文字
    var angles = this.lineNumToAngles(scores.length)
    for (var i = 0; i < angles.length; i++) {
      var angle = angles[i]
      var current = this.polarCoorToCartesianCoor(angle, 100)
      this.drawLine({
        x1: center.x,
        y1: center.y,
        x2: current.x,
        y2: current.y,
        offset: offset,
        color: 'rgba(145, 228, 255, 1)',
        width: 1
      })
      ctx.font = (14 * ratio) + 'px Arial'
      var scoreCoor = this.offsetCartesianCoor(offset, this.getScoreTextCoor(current, this.getQuadrant(current))),
        summaryCoor = this.offsetCartesianCoor(offset, this.getSummaryTextCoor(current, this.getQuadrant(current)))
      if (scores[i] < 100 * pass) ctx.fillStyle = '#FFBE45'
      else ctx.fillStyle = '#32CDFF'
      ctx.fillText(scores[i] + '%', scoreCoor.x * ratio, -scoreCoor.y * ratio)
      ctx.fillText(scoreText[i], summaryCoor.x * ratio, -summaryCoor.y * ratio)
    }

    // 设置总正确率
    this.drawText({
      offset: {
        x: offset.x - 30,
        y: -offset.y * 0.15
      },
      text: summary.overall + '%',
      color: '#32CDFF',
      font: (32 * ratio) + 'px Arial'
    })
    this.drawText({
      offset: {
        x: offset.x - 30,
        y: -offset.y * 0.25
      },
      text: '总正确率',
      color: '#676B75',
      font: (14 * ratio) + 'px Arial'
    })
  }
}